#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "matrix.h"

/*-------------- struct matrix *new_matrix() --------------
Inputs:  int rows
         int cols 
Returns: 

Once allocated, access the matrix as follows:
m->m[r][c]=something;
if (m->lastcol)... 
*/

struct matrix *new_matrix(int rows, int cols) {
  double **tmp;
  int i;
  struct matrix *m;

  tmp = (double **)malloc(rows * sizeof(double *));
  for (i=0;i<rows;i++) {
      tmp[i]=(double *)malloc(cols * sizeof(double));
    }

  m=(struct matrix *)malloc(sizeof(struct matrix));
  m->m=tmp;
  m->rows = rows;
  m->cols = cols;
  m->lastcol = 0;

  return m;
}


/*-------------- void free_matrix() --------------
Inputs:  struct matrix *m 
Returns: 

1. free individual rows
2. free array holding row pointers
3. free actual matrix
*/
void free_matrix(struct matrix *m) {

  int i;
  for (i=0;i<m->rows;i++) {
      free(m->m[i]);
    }
  free(m->m);
  free(m);
}


/*======== void grow_matrix() ==========
Inputs:  struct matrix *m
         int newcols 
Returns: 

Reallocates the memory for m->m such that it now has
newcols number of columns
====================*/
void grow_matrix(struct matrix *m, int newcols) {
  int i;
  for (i=0;i<m->rows;i++) {
      m->m[i] = realloc(m->m[i],newcols*sizeof(double));
    }
  m->cols = newcols;
}


/*-------------- void print_matrix() --------------
Inputs:  struct matrix *m 
Returns: 

print the matrix
*/
void print_matrix(struct matrix *m) {
int xx=m->rows;
int yy=m->cols;
int x;
int y;


for(x=0;x<xx;++x){
	printf("\n");
	for(y=0;y<yy;++y){
		printf("|%d|",m.m[x][y]); //TODO change from %d to whatever it is, chk if its m.m or m->m
	}
}

}

/*-------------- void ident() --------------
Inputs:  struct matrix *m <-- assumes m is a square matrix
Returns: 

turns m in to an identity matrix
*/
void ident(struct matrix *m) {
int xx=m->rows;
int yy=m->cols;
int x;
int y;


for(x=0;x<xx;++x){
	//printf("\n");
	for(y=0;y<yy;++y){
		if(x==y){m.m[x][y]=1;}//TODO chk math, chk if its m.m or m->m
			else{m.m[x][y]=0;}
	}
}

}


/*-------------- void scalar_mult() --------------
Inputs:  double x
         struct matrix *m 
Returns: 

multiply each element of m by x
*/
void scalar_mult(double xd, struct matrix *m) {

int xx=m->rows;
int yy=m->cols;
int x;
int y;


for(x=0;x<xx;++x){
	for(y=0;y<yy;++y){
		m.m[x][y]=m.m[x][y]*xd;//TODO chk math, chk if its m.m or m->m
			
	}
}

}


/*-------------- void matrix_mult() --------------
Inputs:  struct matrix *a
         struct matrix *b 
Returns: 

a*b -> b
*/
void matrix_mult(struct matrix *a, struct matrix *b) {
struct matrix f=new_matrix(b->rows,b->cols);
int x;
int y;
int z;
for(y=0;y<b->rows;++y){
	for(x=0;x<b->cols;++x){
		//f.m[x][y];
		for(z=0;z<a->cols;++z){		
			f.m[x][y]=f.m[x][y]+(a->m[y][z]*b->m[z][x]);
		}
	}
}
copy_matrix(f,b);
free_matrix(f);
}

/*-------------- void copy_matrix() --------------
Inputs:  struct matrix *a
         struct matrix *b 
Returns: 

copy matrix a to matrix b
*/
void copy_matrix(struct matrix *a, struct matrix *b) {

int xx=m->rows;
int yy=m->cols;
int x;
int y;


for(x=0;x<xx;++x){
	for(y=0;y<yy;++y){
		b.m[x][y]=a.m[x][y]//TODO chk math, chk if its m.m or m->m
	}
}

}


